/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * Description: Hmfs-tools resize multi unit test
 */

#include <fcntl.h>
#include <fstream>
#include <ctime>

#include "compare.h"
#include "whole_compare.h"
#include "gtest/gtest.h"
#include "hmfs_test_utils.h"
#include "resize_command.h"

using namespace testing;
using namespace testing::ext;

namespace OHOS {
namespace Hmfs {
constexpr uint32_t LOOP_NUM = 2000;
class ResizeHmfsMultiTest : public testing::Test {
public:
    static void SetUpTestCase();
    static void TearDownTestCase();
    void SetUp() override;
    void TearDown() override;
    uint64_t GetDeviceSectorCount(const std::string &filePath);
	static void ClearTestFile();
};

void ResizeHmfsMultiTest::SetUpTestCase()
{
    system("mount -o remount,rw /");
    system("ln -s /system/bin/fsck.f2fs /system/bin/dump.f2fs");
    CmdConfig resizeConfig;
    ResizeCmdParser resizeParser(resizeConfig);
}

void ResizeHmfsMultiTest::TearDownTestCase()
{
   system("rm -rf /system/bin/dump.f2fs");
}

void ResizeHmfsMultiTest::SetUp() {}

void ResizeHmfsMultiTest::TearDown()
{
    system("rm -rf /data/local/Fs* /data/local/HM*");
}

uint64_t ResizeHmfsMultiTest::GetDeviceSectorCount(const std::string &filePath)
{
    auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
    GetSuperBlock(filePath, hmfsSuperBlock);

    return hmfsSuperBlock->blockCount * DEFAULT_SECTORS_PER_BLOCK;
}

void ResizeHmfsMultiTest::ClearTestFile()
{
	ClearFile(F2FS_DEVICE);
	ClearFile(HMFS_DEVICE);
}

/*
 * @tc.name: ResizeHmfsMultiTest_MultiParams_001
 * @tc.desc: Test resize.hmfs with multiple random parameters.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_MultiParams_001, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_MultiParams_001 BEGIN" << std::endl;
    std::string device = F2FS_DEVICE;
    uint64_t f2fsRunTime = 0;
    ExecutableDdCmd(device, 100);
    ASSERT_EQ(0, ExecMkfsBinary(F2FS_TYPE, device));
    std::string hmDevice = HMFS_DEVICE;
    uint64_t hmfsRunTime = 0;
    ExecutableDdCmd(hmDevice, 100);
    ASSERT_EQ(0, ExecMkfsBinary(HMFS_TYPE, hmDevice));
    // mkfs fsck check
    std::string F2fsMkfsFsckOutFileName = "/data/local/Fsck_F2fs_Mkfs_SingleParams_C_001.txt";
    int32_t fsckMkfsF2fsRes = ExecFsckWithOutput(device, F2fsMkfsFsckOutFileName);
    std::string HmfsMkfsFsckOutFileName = "/data/local/Fsck_Hmfs_Mkfs_SingleParams_C_001.txt";
    int32_t fsckMkfsHmfsRes = ExecFsckWithOutput(hmDevice, HmfsMkfsFsckOutFileName);
    ASSERT_EQ(fsckMkfsF2fsRes, fsckMkfsHmfsRes);
    ASSERT_TRUE(PrintFsckErrorMsg(HmfsMkfsFsckOutFileName, hmDevice));
    if (fsckMkfsHmfsRes == 0) {
        ASSERT_EQ(0, RemoveFile(HmfsMkfsFsckOutFileName));
        ASSERT_EQ(0, RemoveFile(F2fsMkfsFsckOutFileName));
    }

    std::vector<std::string> params;
    params.clear();
    params.push_back("-s");
    params.push_back("-t");
    params.push_back("102400");
    params.push_back("-O");
    params.push_back("extra_attr,project_quota,casefold");
    params.push_back("-C");
    params.push_back("utf8");
    params.push_back("-i");
    params.push_back("-o");
    params.push_back("60");
    params.push_back("-d");
    params.push_back("1");
    ASSERT_EQ(0, ExecResizeBinary(F2FS_TYPE, params, device, f2fsRunTime));
    ASSERT_EQ(0, ExecResizeBinary(HMFS_TYPE, params, hmDevice, hmfsRunTime));

    auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
    GetSuperBlock(device, f2fsSuperBlock);
    auto f2fsCheckPoint = std::make_unique<CheckPointData>();
    GetCheckPoint(device, f2fsCheckPoint);
    auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
    GetSuperBlock(hmDevice, hmfsSuperBlock);
    auto hmfsCheckPoint = std::make_unique<CheckPointData>();
    GetCheckPoint(hmDevice, hmfsCheckPoint);
    std::string HmfsFsckOutFileName = "/data/local/Fsck_Hmfs_MultiParams_001.txt";
    std::string F2fsFsckOutFileName = "/data/local/Fsck_F2fs_MultiParams_001.txt";
    int32_t fsckF2fsRes = ExecFsckWithOutput(hmDevice, HmfsFsckOutFileName);
    int32_t fsckHmfsRes = ExecFsckWithOutput(device, F2fsFsckOutFileName);
    if (fsckF2fsRes == fsckHmfsRes && fsckHmfsRes == 0) {
        if (PrintFsckErrorMsg(F2fsFsckOutFileName, device)) {
            ASSERT_EQ(0, RemoveFile(HmfsFsckOutFileName));
            ASSERT_EQ(0, RemoveFile(F2fsFsckOutFileName));
        }
    }
    ASSERT_EQ(FsBinaryCompare(device, hmDevice), 0);
    (void)CompareRunTime(f2fsRunTime, hmfsRunTime);
    std::cout << "-------------------------------------------------------------------------F2FS" << std::endl;
    PrintSuperBlockAndCheckPointData(device);
    std::cout << "-------------------------------------------------------------------------HMFS" << std::endl;
    PrintSuperBlockAndCheckPointData(hmDevice);
    ASSERT_EQ(FsResultCompare(device, hmDevice), 0);

    std::cout << "ResizeHmfsMultiTest_MultiParams_001 END" << std::endl;
}

/*
 * @tc.name: ResizeHmfsMultiTest_MultiParams_002
 * @tc.desc: Test resize.hmfs with multiple random parameters.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_MultiParams_002, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_MultiParams_002 BEGIN" << std::endl;
    std::srand(std::time(nullptr));
    std::string device = F2FS_DEVICE;
    ExecutableDdCmd(device, 100);
    std::string hmDevice = HMFS_DEVICE;
    ExecutableDdCmd(hmDevice, 100);

    for (int i = 0; i < LOOP_NUM; ++i) {
        ASSERT_EQ(0, ExecMkfsBinary(F2FS_TYPE, device));
        ASSERT_EQ(0, ExecMkfsBinary(HMFS_TYPE, hmDevice));

        // mkfs fsck check
        std::string F2fsMkfsFsckOutFileName = "/data/local/Fsck_F2fs_Mkfs_SingleParams_C_001.txt";
        int32_t fsckMkfsF2fsRes = ExecFsckWithOutput(device, F2fsMkfsFsckOutFileName);
        std::string HmfsMkfsFsckOutFileName = "/data/local/Fsck_Hmfs_Mkfs_SingleParams_C_001.txt";
        int32_t fsckMkfsHmfsRes = ExecFsckWithOutput(hmDevice, HmfsMkfsFsckOutFileName);
        ASSERT_EQ(fsckMkfsF2fsRes, fsckMkfsHmfsRes);
        ASSERT_TRUE(PrintFsckErrorMsg(HmfsMkfsFsckOutFileName, hmDevice));
        if (fsckMkfsHmfsRes == 0) {
            ASSERT_EQ(0, RemoveFile(HmfsMkfsFsckOutFileName));
            ASSERT_EQ(0, RemoveFile(F2fsMkfsFsckOutFileName));
        }

        uint64_t sectorCount = ResizeHmfsMultiTest::GetDeviceSectorCount(hmDevice);
        std::vector<std::string> generateParams = GenerateParams();

        std::map<std::string, std::string> parameterMap{};
        int32_t verifParameters = CheckResizeParameters(hmDevice, generateParams, sectorCount, parameterMap);

        std::string hmfsOutputFile = "/data/local/test_output_hmfs_multi_" + std::to_string(i) + ".txt";
        std::string f2fsOutputFile = "/data/local/test_output_f2fs_multi_" + std::to_string(i) + ".txt";
        int32_t f2fsResult = ExecResizeBinaryWithOutput(F2FS_TYPE, generateParams, device, f2fsOutputFile);
        int32_t hmfsResult = ExecResizeBinaryWithOutput(HMFS_TYPE, generateParams, hmDevice, hmfsOutputFile);

        std::string output = ReadFile(hmfsOutputFile);
        if (f2fsResult != hmfsResult) {
            ClearTestFile();
            continue;
        }
        auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
        GetSuperBlock(device, f2fsSuperBlock);
        auto f2fsCheckPoint = std::make_unique<CheckPointData>();
        GetCheckPoint(device, f2fsCheckPoint);

        auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
        GetSuperBlock(hmDevice, hmfsSuperBlock);
        auto hmfsCheckPoint = std::make_unique<CheckPointData>();
        GetCheckPoint(hmDevice, hmfsCheckPoint);
        PrintSuperBlockAndCheckPointData(hmDevice);

        if (verifParameters == NEED_SAFE_RESIZE_FLAG) {
            ASSERT_TRUE(output.find("Nothing to resize, now only supports resizing with safe resize flag") != std::string::npos);
            ASSERT_EQ(0, RemoveFile(hmfsOutputFile));
            ASSERT_EQ(0, RemoveFile(f2fsOutputFile));
        } else if (verifParameters == OUT_OF_RANGE) {
            ASSERT_TRUE(output.find("Out-of-range Target") != std::string::npos);
            ASSERT_EQ(0, RemoveFile(hmfsOutputFile));
            ASSERT_EQ(0, RemoveFile(f2fsOutputFile));
        } else if (verifParameters == MORE_SEGMENT_NEEDED) {
            ASSERT_TRUE(output.find("Error: Device size is not sufficient for HMFS volume, more segment needed") != std::string::npos);
            ASSERT_EQ(0, RemoveFile(hmfsOutputFile));
            ASSERT_EQ(0, RemoveFile(f2fsOutputFile));
        } else if (verifParameters == VALID) {
            if (hmfsResult == 0) {
                ASSERT_TRUE(!output.empty());
                // 对比hmfs和f2fs字段一致
                SuperBlockCode compSB = CompareSuperBlock(f2fsSuperBlock, hmfsSuperBlock);
                ASSERT_EQ(SUCCESSED_SB, compSB);
                CheckPointCode compCP = ERROR_CP_UNKNOWN;
                if (f2fsCheckPoint != nullptr && hmfsCheckPoint != nullptr) {
                    compCP = CompareCheckPoint(f2fsCheckPoint, hmfsCheckPoint);
                    ASSERT_EQ(SUCCESSED_CP, compCP);
                }
                if (output.find("Info: Done to update superblock") != std::string::npos &&
                    output.find("Info: Done to rebuild checkpoint blocks") != std::string::npos) {
                    ASSERT_TRUE(CheckResizeHmfsResult(parameterMap, hmfsCheckPoint, hmfsSuperBlock, output));
                    if (CheckResizeHmfsResult(parameterMap, hmfsCheckPoint, hmfsSuperBlock, output)) {
                        ASSERT_EQ(0, RemoveFile(hmfsOutputFile));
                        ASSERT_EQ(0, RemoveFile(f2fsOutputFile));
                    }
                } else {
                    ASSERT_EQ(0, RemoveFile(hmfsOutputFile));
                    ASSERT_EQ(0, RemoveFile(f2fsOutputFile));
                }
            }
            std::string HmfsFsckOutFileName = "/data/local/Fsck_Hmfs_MultiParams_002_" + std::to_string(i) + ".txt";
            std::string F2fsFsckOutFileName = "/data/local/Fsck_F2fs_MultiParams_002_" + std::to_string(i) + ".txt";
            int32_t fsckHmfsRes = ExecFsckWithOutput(hmDevice, HmfsFsckOutFileName);
            int32_t fsckF2fsRes = ExecFsckWithOutput(device, F2fsFsckOutFileName);
            if (fsckHmfsRes != fsckF2fsRes) {
                ClearTestFile();
                continue;
            }
            ASSERT_TRUE(PrintFsckErrorMsg(HmfsFsckOutFileName, hmDevice));
            if (fsckHmfsRes == 0) {
                ASSERT_EQ(0, RemoveFile(HmfsFsckOutFileName));
                ASSERT_EQ(0, RemoveFile(F2fsFsckOutFileName));
            }
            if (output.find("Not enough space to migrate blocks") != std::string::npos) {
                ClearTestFile();
                continue;
            }
            if (output.find("Done to rebuild checkpoint blocks") != std::string::npos) {
                ASSERT_EQ(FsBinaryCompare(device, hmDevice), 0);
            } else { // abnormal scence
                if (output.find("Write validId nat_bits in checkpoint") != std::string::npos) {
                    ClearTestFile();
                    continue;
                }
                ASSERT_EQ(FsBinaryCompare(device, hmDevice, false), 0);
            }
            ASSERT_EQ(FsResultCompare(device, hmDevice), 0);
        }
        ClearTestFile();
    }
    std::cout << "ResizeHmfsMultiTest_MultiParams_002 END" << std::endl;
}

/*
 * @tc.name: ResizeHmfsMultiTest_Abnormal_001
 * @tc.desc: Test for abnormal exit during the execution of the resize command.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_Abnormal_001, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_Abnormal_001 BEGIN" << std::endl;
    std::string device = F2FS_DEVICE;
    ExecutableDdCmd(device, 1000);
    ASSERT_EQ(0, ExecMkfsBinary(F2FS_TYPE, device));
    std::vector<std::string> params;
    params.clear();
    auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
    std::string outputFile = "/data/local/test_output.txt";
    pid_t pid = fork();
    if (pid < 0) {
        assert(pid >= 0 && "fork failed with errno = " + std::to_string(errno));
    }
    if (pid == 0) {
        pid_t childId = getpid();
        std::cout << "PID: " << childId << std::endl;
        ASSERT_EQ(0, ExecResizeBinary(F2FS_TYPE, params, device));
        sleep(10);
    }
    usleep(500);
    kill(pid, SIGKILL);
    std::cout << "Child process terminated" << std::endl;
    int status;
    pid_t resid = waitpid(pid, &status, 0);
    std::cout << "id2Kill: " << resid << std::endl;
    ASSERT_EQ(0, ExecResizeBinary(F2FS_TYPE, params, device));
    ASSERT_EQ(0, ExecFsckWithOutput(device, outputFile));
    std::cout << "ResizeHmfsMultiTest_Abnormal_001 END" << std::endl;
}

/*
 * @tc.name: ResizeHmfsMultiTest_Abnormal_002
 * @tc.desc: Test for abnormal exit during the execution of the resize command.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_Abnormal_002, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_Abnormal_002 BEGIN" << std::endl;
    std::string hmDevice = HMFS_DEVICE;
    ExecutableDdCmd(hmDevice, 1000);
    ASSERT_EQ(0, ExecMkfsBinary(HMFS_TYPE, hmDevice));
    std::vector<std::string> params;
    params.clear();
    auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
    std::string outputFile = "/data/local/test_output.txt";
    pid_t pid = fork();
    if (pid < 0) {
        assert(pid >= 0 && "fork failed with errno = " + std::to_string(errno));
    }
    if (pid == 0) {
        pid_t childId = getpid();
        std::cout << "PID: " << childId << std::endl;
        ASSERT_EQ(0, ExecResizeBinary(HMFS_TYPE, params, hmDevice));
        sleep(10);
    }
    usleep(500);
    kill(pid, SIGKILL);
    std::cout << "Child process terminated" << std::endl;
    int status;
    pid_t resid = waitpid(pid, &status, 0);
    std::cout << "id2Kill: " << resid << std::endl;
    ASSERT_EQ(0, ExecResizeBinary(HMFS_TYPE, params, hmDevice));
    ASSERT_EQ(0, ExecFsckWithOutput(hmDevice, outputFile));
    std::cout << "ResizeHmfsMultiTest_Abnormal_002 END" << std::endl;
}

/*
 * @tc.name: ResizeHmfsMultiTest_Abnormal_003
 * @tc.desc: Test for abnormal exit during the execution of the resize command.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_Abnormal_003, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_Abnormal_003 BEGIN" << std::endl;
    std::string device = F2FS_DEVICE;
    ExecutableDdCmd(device, 1000);
    ASSERT_EQ(0, ExecMkfsBinary(F2FS_TYPE, device));
    std::vector<std::string> params;
    uint64_t targetSectors = 102400;
    params.clear();
    params.push_back("-O");
    params.push_back("extra_attr,project_quota");
    params.push_back("-s");
    params.push_back("-t");
    params.push_back(std::to_string(targetSectors));
    std::string outputFile = "/data/local/test_output.txt";
    auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
    pid_t pid = fork();
    if (pid < 0) {
        assert(pid >= 0 && "fork failed with errno = " + std::to_string(errno));
    }
    if (pid == 0) {
        ASSERT_EQ(0, ExecResizeBinary(F2FS_TYPE, params, device));
        sleep(10);
    }
    while (true) {
        GetSuperBlock(device, f2fsSuperBlock);
        uint32_t features = f2fsSuperBlock->features;
        if (features & HMFS_FEATURE_EXTRA_ATTR) {
            kill(pid, SIGKILL);
            break;
        }
    }
    params.clear();
    params.push_back("-s");
    params.push_back("-t");
    params.push_back("102400");
    ASSERT_EQ(0, ExecResizeBinary(F2FS_TYPE, params, device));
    ASSERT_EQ(0, ExecFsckWithOutput(device, outputFile));
    std::cout << "ResizeHmfsMultiTest_Abnormal_003 END" << std::endl;
}

/*
 * @tc.name: ResizeHmfsMultiTest_Abnormal_004
 * @tc.desc: Test for abnormal exit during the execution of the resize command.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_Abnormal_004, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_Abnormal_004 BEGIN" << std::endl;
    std::string hmDevice = HMFS_DEVICE;
    ExecutableDdCmd(hmDevice, 1000);
    ASSERT_EQ(0, ExecMkfsBinary(HMFS_TYPE, hmDevice));
    std::vector<std::string> params;
    uint64_t targetSectors = 102400;
    params.clear();
    params.push_back("-O");
    params.push_back("extra_attr,project_quota");
    params.push_back("-s");
    params.push_back("-t");
    params.push_back(std::to_string(targetSectors));
    std::string outputFile = "/data/local/test_output.txt";
    auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
    pid_t pid = fork();
    if (pid < 0) {
        assert(pid >= 0 && "fork failed with errno = " + std::to_string(errno));
    }
    if (pid == 0) {
        ASSERT_EQ(0, ExecResizeBinary(HMFS_TYPE, params, hmDevice));
        sleep(10);
    }
    while (true) {
        GetSuperBlock(hmDevice, hmfsSuperBlock);
        uint32_t features = hmfsSuperBlock->features;
        if (features & HMFS_FEATURE_EXTRA_ATTR) {
            kill(pid, SIGKILL);
            break;
        }
    }
    params.clear();
    params.push_back("-s");
    params.push_back("-t");
    params.push_back("102400");
    ASSERT_EQ(0, ExecResizeBinary(HMFS_TYPE, params, hmDevice));
    ASSERT_EQ(0, ExecFsckWithOutput(hmDevice, outputFile));
    std::cout << "ResizeHmfsMultiTest_Abnormal_004 END" << std::endl;
}

/*
 * @tc.name: ResizeHmfsMultiTest_Abnormal_005
 * @tc.desc: Test for abnormal exit during the execution of the resize command.
 * @tc.type: FUNC
 */
HWTEST_F(ResizeHmfsMultiTest, ResizeHmfsMultiTest_Abnormal_005, TestSize.Level1)
{
    std::cout << "ResizeHmfsMultiTest_Abnormal_005 BEGIN" << std::endl;
    std::string device = F2FS_DEVICE;
    ExecutableDdCmd(device, 1000);
    ASSERT_EQ(0, ExecMkfsBinary(F2FS_TYPE, device));
    std::string hmDevice = HMFS_DEVICE;
    ExecutableDdCmd(hmDevice, 1000);
    ASSERT_EQ(0, ExecMkfsBinary(HMFS_TYPE, hmDevice));
    std::vector<std::string> params;
    uint64_t targetSectors = 102400;
    params.clear();
    params.push_back("-O");
    params.push_back("extra_attr,project_quota");
    params.push_back("-s");
    params.push_back("-t");
    params.push_back(std::to_string(targetSectors));
    std::string outputFile = "/data/local/test_output.txt";
    auto f2fsSuperBlock = std::make_unique<SuperBlockData>();
    pid_t pid = fork();
    if (pid < 0) {
        assert(pid >= 0 && "fork failed with errno = " + std::to_string(errno));
    }
    if (pid == 0) {
        ASSERT_EQ(0, ExecResizeBinary(F2FS_TYPE, params, device));
        sleep(10);
    }
    while (true) {
        GetSuperBlock(device, f2fsSuperBlock);
        uint32_t features = f2fsSuperBlock->features;
        if (features & HMFS_FEATURE_EXTRA_ATTR) {
            kill(pid, SIGKILL);
            break;
        }
    }
    int status = 0;
    pid_t f2fsPid = waitpid(pid, &status, 0);
    std::cout << "success2kill: " << f2fsPid << std::endl;
    GetSuperBlock(device, f2fsSuperBlock);
    uint32_t f2fsFeatures = f2fsSuperBlock->features;

    auto hmfsSuperBlock = std::make_unique<SuperBlockData>();
    pid_t pidHmfs = fork();
    if (pidHmfs < 0) {
        assert(pid >= 0 && "fork failed with errno = " + std::to_string(errno));
    }
    if (pidHmfs == 0) {
        ASSERT_EQ(0, ExecResizeBinary(HMFS_TYPE, params, hmDevice));
        sleep(10);
    }
    while (true) {
        GetSuperBlock(hmDevice, hmfsSuperBlock);
        uint32_t features = hmfsSuperBlock->features;
        if (features & HMFS_FEATURE_EXTRA_ATTR) {
            kill(pidHmfs, SIGKILL);
            break;
        }
    }
    pid_t hmfsPid = waitpid(pidHmfs, &status, 0);
    std::cout << "success2kill: " << hmfsPid << std::endl;
    GetSuperBlock(hmDevice, hmfsSuperBlock);
    uint32_t hmfsFeatures = hmfsSuperBlock->features;

    ASSERT_EQ(f2fsFeatures, hmfsFeatures);
    ASSERT_EQ(0, ExecResizeBinary(F2FS_TYPE, params, device));
    ASSERT_EQ(0, ExecResizeBinary(HMFS_TYPE, params, hmDevice));
    ASSERT_EQ(0, ExecFsckWithOutput(device, outputFile));
    ASSERT_EQ(0, ExecFsckWithOutput(hmDevice, outputFile));
    std::cout << "ResizeHmfsMultiTest_Abnormal_005 END" << std::endl;
}

} // namespace Hmfs
} // namespace OHOS